﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SharedGenomics.Domain;
using SharedGenomics.Workbench.Services;
using SharedGenomics.Workbench.Core;
using SharedGenomics.Workbench.Views;
using SharedGenomics.Workbench.PresentationModel;
using SharedGenomics.Core;

namespace SharedGenomics.Workbench.Presenters
{
    public class EditUserMarkerPresenter : Presenter, IEditUserMarkerPresenter
    {
        public EditUserMarkerPresenter(IEditUserMarkerView view, ISnpService snpService)
            : base(view)
        {
            this.EditMarkerView = view;
            this.SnpService = snpService;

            this.EditMarkerView.EditEnded += new EventHandler(this.View_EditEnded);
            this.EditMarkerView.EditingRsNumberChanged += new EventHandler(this.View_EditingRsNumberChanged);

            //setup PTO and set on the view
            this.PTO = new EditUserMarkerPTO() { EditingRsNumber = true };
            this.PTO.ValidationChanged += new EventHandler<ValidationErrorsNotificationEventArgs>(this.PTO_ValidationChanged);
            view.PTO = this.PTO;
        }

        private void PTO_ValidationChanged(object sender, ValidationErrorsNotificationEventArgs e)
        {
            this.View.ValidationErrors = e.ValidationErrors;
        }

        private void View_EditEnded(object sender, EventArgs e)
        {
            //SnpMarkerInfo marker = this.EditMarkerView.Marker;
            bool editingRsNumber = this.EditMarkerView.EditingRsNumber;

            if (this.PTO.Validate())
            {
                //try to update marker information via the snp service
                string errorMessage;
                Maybe<bool> updateState;
                string markerName = this.PTO.MarkerName;
                int chromosome;
                long position;

                if (editingRsNumber)
                {
                    int rsNumber = Int32.Parse(this.PTO.RsNumber);
                    updateState = this.SnpService.SetUserMarker(markerName, rsNumber, out chromosome, out position, out errorMessage);
                }
                else
                {
                    chromosome = Chromosome.Parse(PTO.Chromosome);
                    position = long.Parse(PTO.Position);

                    updateState = this.SnpService.SetUserMarker(markerName, chromosome, position, out errorMessage);
                }

                updateState.BindAction(updateSuccessful =>
                {
                    if (updateSuccessful)
                    {
                        //if the update was successful, the view datasource should be updated to reflect any new information and any interested listeners 
                        //should be informed that the marker details were added
                        this.EditMarkerView.ServiceMessage = String.Format("Details for {0} set successfully", markerName);

                        this.MarkerUpdated.Raise(this, new MarkerUpdatedEventArgs(markerName));
                    }
                    else
                    {
                        //display service error message
                        this.EditMarkerView.ServiceMessage = String.Format("Unable to set SNP information: {0}", errorMessage);
                    }
                });
            }
            else
            {
                //clear service message
                this.EditMarkerView.ServiceMessage = null;
            }
        }

        private void View_EditingRsNumberChanged(object sender, EventArgs e)
        {
            bool editingRsNumber = this.EditMarkerView.EditingRsNumber;

            //if the rs number can be edited, then the chromosome and position field cannot be edited (and visa/versa if the rs number is not being edited)
            this.EditMarkerView.IsRsNumberEnabled = editingRsNumber;
            this.EditMarkerView.IsChromosomeEnabled = !editingRsNumber;
            this.EditMarkerView.IsPositionEnabled = !editingRsNumber;
        }

        private ISnpService SnpService { get; set; }
        private IEditUserMarkerView EditMarkerView { get; set; }
        private EditUserMarkerPTO PTO { get; set; }

        public void LoadMarker(string markerName)
        {
            this.LoadMarker(new SnpMarkerInfo() { MarkerName = markerName });
        }

        public void LoadMarker(SnpMarkerInfo markerInfo)
        {
            this.PTO.MarkerName = markerInfo.MarkerName;
            this.PTO.RsNumber = markerInfo.RsNumber;
            this.PTO.Chromosome = markerInfo.Chromosome;
            this.PTO.Position = markerInfo.Position;
        }

        public event EventHandler<MarkerUpdatedEventArgs> MarkerUpdated;
    }
}
